Fernando Martinelli Ramacciotti 301002

MPE | Econometria das Séries Financeiras - Quiz 3

fernandoramacciotti@gmail.com


Análise empírica do prêmio de risco de crédito

In [1]:
%matplotlib inline
import numpy as np
import pandas as pd
import os
from scipy import stats

import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.graphics.api import qqplot

import plotly
plotly.offline.init_notebook_mode()
import plotly.offline as po
import plotly.plotly as py
import plotly.graph_objs as go
import cufflinks as cf
import plotly.figure_factory as ff
C:\Anaconda3\lib\site-packages\statsmodels\compat\pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.
  from pandas.core import datetools
In [2]:
excel = pd.ExcelFile('./dados/IndicesDeCredito.xlsx')
In [3]:
dados = pd.DataFrame()

print('Dados sobre:')

for tab in excel.sheet_names:
    print(tab)
    df = excel.parse(tab, index_col = 0, skiprows = 1)
    if df.shape[1] > 1:
        df.columns = excel.parse(tab, skiprows = 0, index_col = 0).columns
    else:
        df.columns = [tab]
    df.index.name = 'Dates'
    dados = pd.concat([dados, df],join='outer',axis=1)
Dados sobre:
Eurobonds
BRSvg
UST
NTNBs
RealYield5Y
NominalYield5Y
DebenturesIPCA
CDI
DebenturesCDI
In [4]:
dados.dropna().tail()
Out[4]:
Eurobonds Eurobonds_Duration BRSvg BRSvg_Duration UST UST_Duration NTNBs RealYield5Y NominalYield5Y DebenturesIPCA CDI DebenturesCDI
Dates
2017-03-27 527.259 4.843 1717.002 7.877 1570.122 6.207 6109.589 5.212 10.015 2092.616172 47.182706 1971.332550
2017-03-30 530.748 4.849 1722.865 7.881 1566.508 6.178 6089.439 5.295 9.998 2088.980180 47.247057 1974.653600
2017-04-04 530.928 4.951 1738.090 7.900 1572.291 6.260 6100.761 5.260 9.853 2093.135111 47.311496 1978.284842
2017-04-07 531.227 4.932 1728.620 7.838 1570.533 6.248 6054.162 5.309 9.984 2094.199664 47.376024 1981.358101
2017-04-11 532.786 4.922 1742.526 7.873 1577.881 6.271 6077.123 5.279 9.920 2096.777842 47.419091 1983.304586

Eurobonds vs. BR Svg vs. UST

Mediremos o excesso de retorno ajustado por Duration e ver se há prêmio de risco

i) BR Svg vs. UST

$R_{t+1}^{BRSvg-XS}=R_{t+1}^{BRSvg} - \frac{D_t^{BRSvg}}{D_t^{UST}} R_{t+1}^{UST}$

ii) Eurobonds vs. BRSvg

$R_{t+1}^{EUR-XS}=R_{t+1}^{EUR} - \frac{D_t^{EUR}}{D_t^{BRSvg}} R_{t+1}^{BRSvg}$

In [5]:
debts = pd.DataFrame()

debts = dados.loc[:, ~dados.iloc[:, :6].columns.str.contains('Duration')].resample('M').last().pct_change(1)

debts = pd.concat([debts, dados.loc[:, dados.iloc[:, :6].columns.str.contains('Duration')].resample('M').last().shift(1)], 
                  axis = 1, join = 'inner')

debts.dropna(inplace=True)
In [6]:
print('Periodo de analise:')
print(min(debts.index))
print(max(debts.index))
print(str(debts.shape[0] - 1) + ' months')
Periodo de analise:
1999-02-28 00:00:00
2017-04-30 00:00:00
218 months
In [7]:
risk_premia = pd.DataFrame()
risk_premia['BRSvg_xs'] = debts['BRSvg'] - (debts['BRSvg_Duration'] / debts['UST_Duration']) * debts['UST']
risk_premia['EUR_xs'] = debts['Eurobonds'] - (debts['Eurobonds_Duration'] / debts['BRSvg_Duration']) * debts['BRSvg']

for col in risk_premia.columns:
    risk_premia[col + '_cum'] = (1 + risk_premia[col]).cumprod() - 1
In [8]:
cf.go_offline()
cf.set_config_file(offline=True, world_readable=False, theme='ggplot')

#fig = risk_premia.iplot(secondary_y = [col for col in risk_premia.columns if '_cum' in col])


fig1 = risk_premia.iplot(columns = [col for col in risk_premia.columns if '_cum' not in col], 
                         kind = 'bar', 
                         asFigure=True)
fig2 = risk_premia.iplot(columns = [col for col in risk_premia.columns if '_cum' in col], 
                secondary_y = [col for col in risk_premia.columns if '_cum' in col], 
                asFigure=True)

fig2['data'].extend(fig1['data'])
fig2['layout']['title'] = 'Premio de risco de credito de BRSvg e Eurobonds'
fig2['layout']['yaxis1']['title'] = 'Premio de risco mensal (barras)'
fig2['layout']['yaxis2']['title'] = 'Premio de risco acumulado (linhas)'


po.iplot(fig2)
C:\Anaconda3\lib\site-packages\cufflinks\plotlytools.py:156: FutureWarning:

pandas.tslib is deprecated and will be removed in a future version.
You can access Timestamp as pandas.Timestamp

In [9]:
risk_premia['BRSvg_xs_simple'] = debts['BRSvg'] - debts['UST']
risk_premia['EUR_xs_simple'] = debts['Eurobonds'] - debts['BRSvg']
In [10]:
data_matrix =  [[''] + [i for i in risk_premia.columns if '_cum' not in i],
               ['Mean'] + [str(round((((1 + risk_premia[i].mean()) ** (12)) - 1)*100, 2)) + '%' 
                           for i in risk_premia.columns if '_cum' not in i],
               ['Vol.'] + [str(round(((np.log(1+risk_premia[i]).std()) * np.sqrt(12))*100, 2)) + '%' 
                               for i in risk_premia.columns if '_cum' not in i],
               ['Sharpe'] + [round(((((1 + risk_premia[i].mean()) ** (12)) - 1) / (risk_premia[i].std() * np.sqrt(12))), 2) 
                             for i in risk_premia.columns if '_cum' not in i]]

table = ff.create_table(data_matrix)
po.iplot(table)

Comparando os retornos anualizados e os respectivos Sharpe Ratios, notamos que existe premio de risco para divida soberana brasileira (BRSvg), medido pelo excesso de retorno de BRSvg em relação a UST. No entanto, nota-se que a Duration de ambos, na média, é muito parecida, pois o excesso de retorno simples e ajustado por duration são muito próximos. Na realiade, o Sharpe Ratio do exesso simples é ligeiramente maior.

Já para Eurobonds, notamos que o premio de risco vs. BRSvg não existe.


Debêntures

Estimaremos o excesso de retorno das Debentures ligadas ao IPCA e ao CDI.

Para isso, primeiramente rodaremos uma regressão para estimarmos os $\beta$'s como proxy de Duration

i) ID-IPCA

estimar: $R_{t+1}^{DebIPCA} = \alpha + \beta^{DebIPCA}{\Delta}y_{t+1}^{real} + \epsilon_t$

estimar: $R_{t+1}^{Gov} = \alpha + \beta^{Gov}{\Delta}y_{t+1}^{real} + \epsilon_t$

calcular: $R_{t+1}^{DebIPCA-XS}=R_{t+1}^{DebIPCA} - \frac{\beta^{DebIPCA}}{\beta^{Gov}} R_{t+1}^{Gov}$

In [11]:
debentures = pd.DataFrame()

indices = pd.DataFrame()
for col in dados.iloc[:, 6:].columns:
    if 'Yield' not in col:
        indices[col] = dados[col]

yields = pd.DataFrame()
for col in dados.iloc[:, 6:].columns:
    if 'Yield' in col:
        yields[col] = dados[col]
    
indices = indices.resample('BM').last()
indices = indices.pct_change(1)
yields = yields.resample('BM').last()
yields = yields - yields.shift(1)

debentures = pd.concat([indices, yields], axis = 1, join = 'outer').ffill().dropna()
In [12]:
# regressao para achar beta DebIPCA
reg = sm.OLS(endog = debentures['DebenturesIPCA'], exog = sm.add_constant(debentures['RealYield5Y']), hasconst = True)
reg_deb_ipca = reg.fit()
print(reg_deb_ipca.summary())

# regressao para achar beta Gov
reg = sm.OLS(endog = debentures['NTNBs'], exog = sm.add_constant(debentures['RealYield5Y']), hasconst = True)
reg_gov = reg.fit()
print(reg_gov.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:         DebenturesIPCA   R-squared:                       0.726
Model:                            OLS   Adj. R-squared:                  0.721
Method:                 Least Squares   F-statistic:                     145.5
Date:                Tue, 20 Jun 2017   Prob (F-statistic):           4.44e-17
Time:                        03:26:57   Log-Likelihood:                 209.82
No. Observations:                  57   AIC:                            -415.6
Df Residuals:                      55   BIC:                            -411.6
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
===============================================================================
                  coef    std err          t      P>|t|      [0.025      0.975]
-------------------------------------------------------------------------------
const           0.0101      0.001     12.181      0.000       0.008       0.012
RealYield5Y    -0.0313      0.003    -12.063      0.000      -0.036      -0.026
==============================================================================
Omnibus:                       19.170   Durbin-Watson:                   1.836
Prob(Omnibus):                  0.000   Jarque-Bera (JB):               27.729
Skew:                          -1.197   Prob(JB):                     9.52e-07
Kurtosis:                       5.438   Cond. No.                         3.16
==============================================================================

Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                  NTNBs   R-squared:                       0.628
Model:                            OLS   Adj. R-squared:                  0.621
Method:                 Least Squares   F-statistic:                     92.78
Date:                Tue, 20 Jun 2017   Prob (F-statistic):           2.10e-13
Time:                        03:26:57   Log-Likelihood:                 143.82
No. Observations:                  57   AIC:                            -283.6
Df Residuals:                      55   BIC:                            -279.6
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
===============================================================================
                  coef    std err          t      P>|t|      [0.025      0.975]
-------------------------------------------------------------------------------
const           0.0108      0.003      4.101      0.000       0.006       0.016
RealYield5Y    -0.0795      0.008     -9.632      0.000      -0.096      -0.063
==============================================================================
Omnibus:                        6.899   Durbin-Watson:                   2.441
Prob(Omnibus):                  0.032   Jarque-Bera (JB):                9.540
Skew:                           0.319   Prob(JB):                      0.00848
Kurtosis:                       4.900   Cond. No.                         3.16
==============================================================================

Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

Ambos $\beta$'s são significantes, então podemos, agora, estimar o excesso de retorno ajustado por duration (ou $\beta$)

In [13]:
print('Beta DebIPCA = %.3f' %reg_deb_ipca.params[1])
print('Beta Gov = %.3f' %reg_gov.params[1])
Beta DebIPCA = -0.031
Beta Gov = -0.079
In [14]:
deb_ipca = pd.DataFrame()
deb_ipca['DebIPCA_xs'] = debentures['DebenturesIPCA'] - (reg_deb_ipca.params[1] / reg_gov.params[1]) * debentures['NTNBs']
deb_ipca['DebIPCA_xs_simple'] = debentures['DebenturesIPCA'] - debentures['NTNBs']
for col in deb_ipca.columns:
    deb_ipca[col + '_cum'] = (1 + deb_ipca[col]).cumprod() - 1
In [15]:
cf.go_offline()
cf.set_config_file(offline=True, world_readable=False, theme='ggplot')

fig1 = deb_ipca.iplot(columns = [col for col in deb_ipca.columns if '_cum' not in col], 
                         kind = 'bar', 
                         asFigure=True)
fig2 = deb_ipca.iplot(columns = [col for col in deb_ipca.columns if '_cum' in col], 
                secondary_y = [col for col in deb_ipca.columns if '_cum' in col], 
                asFigure=True)

fig2['data'].extend(fig1['data'])
fig2['layout']['title'] = 'Premio de risco ID-IPCA'
fig2['layout']['yaxis1']['title'] = 'Premio de risco mensal (barras)'
fig2['layout']['yaxis2']['title'] = 'Premio de risco acumulado (linhas)'


po.iplot(fig2)
In [16]:
data_matrix =  [[''] + [i for i in deb_ipca.columns if '_cum' not in i],
               ['Mean'] + [str(round((((1 + deb_ipca[i].mean()) ** (12)) - 1)*100, 2)) + '%' 
                           for i in deb_ipca.columns if '_cum' not in i],
               ['Vol.'] + [str(round(((np.log(1+deb_ipca[i]).std()) * np.sqrt(12))*100, 2)) + '%' 
                               for i in deb_ipca.columns if '_cum' not in i],
               ['Sharpe'] + [round(((((1 + deb_ipca[i].mean()) ** (12)) - 1) / (deb_ipca[i].std() * np.sqrt(12))), 2) 
                             for i in deb_ipca.columns if '_cum' not in i]]

table = ff.create_table(data_matrix)
po.iplot(table)

Nota-se que há um alto premio de risco, e com alto Sharpe, para o excesso de retorno ajustado por duration.

Devemos tomar cuidado, no entanto, pois a amostra é pequena e foi necessário preencher as lacunas com o método Forward-Fill para ter-se uma série contínua.

ii) ID-CDI

calcular e ver significancia do $\beta$: $R_{t+1}^{DebCDI} - R_{t+1}^{CDI} = \alpha + \beta^{DebCDI}{\Delta}y_{t+1}^{nom}$

In [17]:
# regressao para achar beta DebCDI
reg = sm.OLS(endog = debentures['DebenturesCDI'] - debentures['CDI'], 
             exog = sm.add_constant(debentures['NominalYield5Y']), 
             hasconst = True)
reg_deb_cdi = reg.fit()
print(reg_deb_cdi.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                      y   R-squared:                       0.000
Model:                            OLS   Adj. R-squared:                 -0.018
Method:                 Least Squares   F-statistic:                  0.009500
Date:                Tue, 20 Jun 2017   Prob (F-statistic):              0.923
Time:                        03:26:57   Log-Likelihood:                 289.78
No. Observations:                  57   AIC:                            -575.6
Df Residuals:                      55   BIC:                            -571.5
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==================================================================================
                     coef    std err          t      P>|t|      [0.025      0.975]
----------------------------------------------------------------------------------
const              0.0011      0.000      5.231      0.000       0.001       0.001
NominalYield5Y  -3.51e-05      0.000     -0.097      0.923      -0.001       0.001
==============================================================================
Omnibus:                       14.749   Durbin-Watson:                   1.317
Prob(Omnibus):                  0.001   Jarque-Bera (JB):               66.253
Skew:                          -0.092   Prob(JB):                     4.10e-15
Kurtosis:                       8.278   Cond. No.                         1.78
==============================================================================

Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

O coeficiente nao é significante. Não podemos, então, concluir se há premio de risco para o caso de ID-CDI.